/// Controller for Algorithms
/// Loads each algorithm into a hash map with the key being the algorithm's name defined in its class
/// To load an algorithm create an instance of algorithms and use GetAlgorithm. If an algorithm can't be loaded
/// it defaults to the UserInput algorithm and throws an exception if that fails.

using System;
using System.Collections.Generic;
using System.Text;

namespace Autobot
{
    class Algorithms
    {
        // Hashmap of all algorithms, must be the same across all instances
        private static Dictionary<string, AlgorithmBase> algorithms;

        /// <summary>
        /// Constructor for Algorithms: Load an instance of each type of algorithm so a user can retrive the
        /// algorithm they want by the string name of the algorithm defined in the algoritihm class under 'Name'.
        /// Requires the parameters all algorithms need: The map, the robot, and the goal
        /// </summary>
        /// <param name="map">Reference to the map associated with the robot and goal</param>
        /// <param name="robot">Robot the algorithm will give commands to</param>
        /// <param name="goal">The goal the robot is trying to reach</param>
        public Algorithms(VirtualMap map, Robot robot, Goal goal)
        {
            // Create the hashmap
            algorithms = new Dictionary<string, AlgorithmBase>();
            // Fill the hashmap with an instance of each algorithm
            // If an exception occurs report it and continue adding algorithms
            try { algorithms.Add(SupermanAlgorithm.Name.ToLower(), new SupermanAlgorithm(map, robot, goal)); }
            catch { Console.WriteLine("Could not add SupermanAlgorithm to algorithms hash!"); }
            try { algorithms.Add(UserInputAlgorithm.Name.ToLower(), new UserInputAlgorithm(map, robot, goal)); }
            catch { Console.WriteLine("Could not add UserInputAlgorithm to algorithms hash!"); }
            try { algorithms.Add(Mulletgorithm.Name.ToLower(), new Mulletgorithm(map, robot, goal)); }
            catch{ Console.WriteLine("Could not add Mulletgorithm to algorithms hash!"); }
            try { algorithms.Add(Britishgorithm.Name.ToLower(), new Britishgorithm(map, robot, goal)); }
            catch { Console.WriteLine("Could not add Britishgorithm to algorithms hash!"); }
        }

        /// <summary>
        /// Get a loaded algorithm for use based on the name of the algorithm
        /// Default to the UserInput algorithm if no algorithm is found
        /// </summary>
        /// <param name="name">String name of the algorithm to load defined in the algorithm class</param>
        /// <returns>The algorithm instance with the name given </returns>
        public AlgorithmBase GetAlgorithm(string name)
        {
            // Make sure the name is all lower case (same case as all algorithm names)
            name = name.ToLower();
            AlgorithmBase returnAlg = null;
            // Try and get the algorithm for the name. If the name doesn't exist in the algorithms hash return null
            if (algorithms.ContainsKey(name))
                returnAlg = algorithms[name];
            // Return the algorithm
            return returnAlg;
        }

        /// <summary>
        /// Get the key for each algorithm stored in the algorithms hash map
        /// </summary>
        /// <returns>A list of strings which are a key for each algorithm stored in the hash</returns>
        public List<string> GetAlgorithms()
        {
            List<string> keys = new List<string>();
            foreach (KeyValuePair<string, AlgorithmBase> key in algorithms)
                keys.Add(key.Key);
            return keys;
        }

    }
}
